package com.ming.common.dynamic.loader.class_loader;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLClassLoader;
import java.security.SecureClassLoader;

/**
 * 动态编译加载器
 */
public class DynamicClassLoader extends SecureClassLoader {

    /**
     * 编译的时候返回的class字节数组
     */
    private byte[] classData;

    public DynamicClassLoader(byte[] classData) {
        super();
        this.classData = classData;
    }

    @Override
    protected Class<?> findClass(String fullClassName) throws ClassNotFoundException {
        // 1.编译的class字节数组为null，则说明已经编译过了，是后续的调用，不用编译
        if (classData == null || classData.length == 0) {
            throw new ClassNotFoundException("[动态编译]classdata不存在");
        }
        try {
            //System.out.println(fullClassName);
            //Class.forName(fullClassName, false, this.getClass().getClassLoader());
            // 2.加载
            return defineClass(fullClassName, classData, 0, classData.length);
        } catch (Exception e) {
            System.out.println("loader error: "+fullClassName);
        }
        return null;
    }

    public boolean loadClassFromURLClassLoader(URLClassLoader urlClassLoader, String className) {
        try {
            Class<?> loadedClass = urlClassLoader.loadClass(className);
            InputStream classStream = loadedClass.getResourceAsStream("/" + className.replace('.', '/') + ".class");
            byte[] classBytes = readStreamToBytes(classStream);
            defineClass(className, classBytes, 0, classBytes.length);
            return true;
        }catch (Exception e){
            e.printStackTrace();
            return false;
        }
    }

    private byte[] readStreamToBytes(InputStream in) throws IOException {
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        byte[] buffer = new byte[1024];
        int bytesRead;
        while ((bytesRead = in.read(buffer)) != -1) {
            out.write(buffer, 0, bytesRead);
        }
        return out.toByteArray();
    }
}

